#include "disp.h"
#include "bitmap.h"
#include "rtc.h"
#include <Adafruit_NeoPixel.h>
#include "ui.h"

Adafruit_NeoPixel strip(256, 23, NEO_GRB + NEO_KHZ800);

// extern SHT31D sht_res;
static uint8_t current_bright; /*Max is 100*/
static uint8_t blinker_config_bright;
static uint32_t disp_buf[8][32];

void rgbInit(void)
{
    strip.begin();   
    setConfigBrightness(50);
    setFontColor(0x00FF20);
}

void drawPoint(int8_t x, int8_t y, uint8_t en, uint32_t pixel_color)
{
    if(x>=0 && x<32 && y>=0 && y<8)
    {
        disp_buf[y][x] = pixel_color*en;
    }
}

uint8_t drawChar(char c, int8_t x, int8_t y, uint8_t height, uint32_t pixel_color)
{
    uint8_t i = 0, j = 0, a = 0, weight = 0;
    uint8_t t, x1, y1;

    x1 = x;
    y1 = y;
    a = c - ' ';

    for(i=0; i<height; i++, y1++, x1 = x)
    {
        t = pgm_read_byte_far(&font[a][i]);
        for(j=0; j<8; j++, x1++)
        {
            drawPoint(x1, y1, (t&0x80)>>7, pixel_color);
            t <<= 1;
        }
    }
    weight = pgm_read_byte_far(&font[a][5]);
    return weight;
}

uint8_t drawCharGradient(char c, int8_t x, int8_t y, uint8_t height, uint32_t start_color, uint32_t end_color)
{
    uint8_t i = 0, j = 0, a = 0, weight = 0;
    uint8_t t, x1, y1;
    uint8_t r_s = 0, g_s = 0, b_s = 0;
    uint8_t r_e = 0, g_e = 0, b_e = 0;
    int8_t rr = 0, gg = 0, bb = 0;

    r_s = (start_color>>16)&0xFF;
    g_s = (start_color>>8)&0xFF;
    b_s = start_color&0xFF;

    r_e = (end_color>>16)&0xFF;
    g_e = (end_color>>8)&0xFF;
    b_e = end_color&0xFF;

    rr = (r_e-r_s)/height;
    gg = (g_e-g_s)/height;
    bb = (b_e-b_s)/height;

    x1 = x;
    y1 = y;
    a = c - ' ';

    for(i=0; i<height; i++, y1++, x1 = x)
    {
        t = pgm_read_byte_far(&font[a][i]);
        for(j=0; j<8; j++, x1++)
        {
            drawPoint(x1, y1, (t&0x80)>>7, (((uint32_t)(r_s+rr*i)<<16) | ((uint32_t)(g_s+gg*i)<<8) | (uint32_t)(b_s+bb*i)));
            t <<= 1;
        }
    }
    weight = pgm_read_byte_far(&font[a][5]);
    return weight;
}

void drawNum(uint8_t num, int8_t x, int8_t y, uint32_t pixel_color)
{
    uint8_t pos = 0;
    pos = drawChar(num/10+48, x, y, 5, pixel_color);
    pos = drawChar(num%10+48, x+pos+1, y, 5, pixel_color);
}

void drawNumGradient(uint8_t num, int8_t x, int8_t y, uint32_t start_color, uint32_t end_color)
{
    uint8_t pos = 0;
    pos = drawCharGradient(num/10+48, x, y, 5, start_color, end_color);
    pos = drawCharGradient(num%10+48, x+pos+1, y, 5,  start_color, end_color);
}

void drawString(char *p, int8_t x, int8_t y, uint32_t pixel_color)
{
	char *ps;
    uint8_t pos = 0;

	while(1)
	{
		ps = p++;
		pos = drawChar(*ps, x, y, 5, pixel_color);
		x += (pos+1);
		if(*p=='\0' || x>31)		
			break;
	}
}

void drawStringGradient(char *p, int8_t x, int8_t y, uint32_t start_color, uint32_t end_color)
{
	char *ps;
    uint8_t pos = 0;

	while(1)
	{
		ps = p++;
		pos = drawCharGradient(*ps, x, y, 5, start_color, end_color);
		x += (pos+1);
		if(*p=='\0' || x>31)		
			break;
	}
}

void drawBitmapRGB(const uint32_t *p, int8_t x, int8_t y, uint8_t w, uint8_t h)
{
    int8_t x1, y1, w1, h1, i;

    w1 = x+w;
    h1 = y+h;
    
    for(y1=y; y1<h1; y1++)
    {
        for(x1=x; x1<w1; x1++, i++, p++)
        {
            drawPoint(x1, y1, 1, *p);
        }
    }
}

void sendToScreen(void)
{
    uint8_t i = 0, j = 0;
    uint32_t col = 0;

    for(i=0; i<32; i++)
    {
        for(j=0; j<8; j++)
        {
            col = disp_buf[j][i];
            if(i%2 == 0)
                strip.setPixelColor(8*i+j, col);
            else
                strip.setPixelColor(8*(i+1)-1-j, col);
        }
    }
    strip.show();
}

void clearScreen(void)
{
    uint8_t i, j;
    for(i=0; i<8; i++)
        for(j=0; j<32; j++)
            disp_buf[i][j] = 0;
    strip.clear();
}

void setCurrentBrightness(uint8_t bright)
{
    float f_brightness = bright/100.0;
    uint8_t u_brightness = f_brightness * 255;
    current_bright = bright;
    strip.setBrightness(u_brightness);
}

uint8_t getCurrentBrightness(void)
{
    return current_bright;
}

void setConfigBrightness(uint8_t bright)
{
    blinker_config_bright = bright;
}

uint8_t getConfigBrightness(void)
{
    return blinker_config_bright;
}

void brightControlTask(void)
{
    static uint16_t cnt = 0;
    uint16_t ad_value = 0;
    if(ad_enable)
    {
        ad_value = analogRead(34);    
        // Serial.printf("ad value:%d\r\n", ad_value);
        if(ad_value < 1000)
        {
            cnt++;
            if(cnt >= 50 && ((rtc.hour>=0 && rtc.hour<8) || rtc.hour==23))
                setCurrentBrightness(0);
            else
                setCurrentBrightness(blinker_config_bright/2);
        }
        else
        {
            cnt = 0;
            setCurrentBrightness(blinker_config_bright);
        }
    }
}
